<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style lang="">
        .zoom {
            cursor: move;
            fill: none;
            pointer-events: all;
        }
    </style>
</head>

<body>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script>
        // mock1000条正态分布随机数据
        var data = d3.range(1000).map(d3.randomNormal(80, 10));
        data.sort(function (a, b) { return a - b; });

        //画布长宽
        var svgWidth = 800;
        var svgHeight = 300;

        //画布在容器内的大小
        var margin = { top: 30, right: 40, bottom: 50, left: 60 };

        //绘制图标的宽高
        var width = svgWidth - margin.left - margin.right;
        var height = svgHeight - margin.top - margin.bottom;

        //图表容器
        var svg = d3.select("body")
            .append('svg')
            .attr('width', svgWidth)
            .attr('height', svgHeight)

        //创建横坐标时间轴比例尺 d3.extent取数组的范围
        var x = d3.scaleLinear()
            .domain(d3.extent(data))
            .range([0, width]);
        // xdomain = [new Date('2018-3-5 00:00:00'), new Date('2018-3-11 23:59:59')]
        // x = d3.scaleTime()
        //     .domain(xdomain)
        //     .range([0, svgWidth])

        //mock纵坐标数据
        var ticks = { req: { min: 5, max: 40 }, got: [] };
        var t = 0;
        var tickData = d3.range(ticks.req.min, ticks.req.max + 1, 1)
        tickData.forEach(function (d) {
            if (x.ticks(d).length > t) {
                t = x.ticks(d).length;
                ticks.got.push(x.ticks(d).length)
            }
        });
        ticks.def = ticks.got[Math.round(ticks.got.length / 2) - 1];
        ticks.cur = ticks.def;
        console.log(ticks)
        var bins = binData(data, x, ticks.def);
        console.log(bins)

        //创建纵坐标比例尺 取纵坐标数据的最大值
        var y = d3.scaleLinear()
            .domain([0, d3.max(bins.map(function (d) { return d.count }))])
            .range([height, 0]);

        //横坐标纵坐标容器
        var xAxis = d3.axisBottom(x);
        var yAxis = d3.axisLeft(y);

        //图表缩放绑定方法
        var zoom = d3.zoom()
            .on("zoom", zoomFunction);

        svg.call(zoom)

        //在svg容器内插入g标签并绑定缩放函数并使用transform固定该标签到横纵坐标上
        var innerSpace = svg.append("g")
            .attr("class", "inner_space")

            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        // .call(zoom);

        //================================>>>>直方图相关
        // 创建直方图容器
        var bar = innerSpace.append("g")
            .attr('clip-path', 'url(#my-clip-path)')
            .attr("width", width)
            .attr("height", height)
        // .call(zoom)

        // 创建每个柱状图形
        bar.selectAll(".bar")
            .data(bins)
            .enter()
            .append("rect")
            .attr("class", "bar")
            .attr("width", x(bins[0].max) - x(bins[0].min) - 2)
            .attr("height", function (d) { return height - y(d.count) })
            .attr("x", function (d) { return x(d.min) })
            .attr("y", function (d) { return y(d.count) })

        //绘制横坐标
        var gX = innerSpace.append("g")
            .attr("class", "axis axis--x")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        //绘制纵坐标
        var gY = innerSpace.append("g")
            .attr("class", "axis axis--y")
            .call(yAxis);

        //创建一个rect绑定缩放事件
        var view = innerSpace.append("g")
            .attr("class", "zoom")
            .attr("width", width)
            .attr("height", height)
        // .call(zoom)



        function zoomFunction() {
            if (d3.event.transform.k < 1) {
                d3.event.transform.k = 1
                return
            }
            // 基于事件创建一个新的比例尺
            var new_xScale = d3.event.transform.rescaleX(x)
            // var new_yScale = d3.event.transform.rescaleY(y)

            // 更新横坐标和纵坐标
            gX.call(xAxis.scale(new_xScale));
            // gY.call(yAxis.scale(new_yScale));
            console.log(d3.event.transform)
            bar.attr("transform", `translate(${d3.event.transform.x},0) scale(${d3.event.transform.k},1)`)
                .attr("width", width)
                .attr("height", height)
        };

        function binData(dat, s, t) {
            var b = [];

            // 取值域数
            s.ticks(t).forEach(function (d, i) {
                if (i < x.ticks(t).length - 1) {
                    b.push({ bin: i, min: d, max: x.ticks(t)[i + 1] })
                }
            });

            // 取在值域范围内的count数
            b.forEach(function (d) {
                d.count = dat.filter(function (e) { return e >= d.min && e < d.max }).length;
            })

            return b;
        }
    </script>
</body>

</html>